package com.graduate.emos.wx.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.graduate.emos.wx.common.util.R;
import com.graduate.emos.wx.common.util.SystemConstants;
import com.graduate.emos.wx.config.shiro.JwtUtil;
import com.graduate.emos.wx.controller.form.CheckinForm;
import com.graduate.emos.wx.controller.form.SearchMonthCheckinForm;
import com.graduate.emos.wx.exception.EmosException;
import com.graduate.emos.wx.service.CheckinService;
import com.graduate.emos.wx.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.*;

@RequestMapping("/checkin")
@Slf4j
@Api("签到模块web接口")
@RestController
public class CheckinController {

    /*注入对象*/
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private CheckinService checkinService;
    @Autowired
    private UserService userService;
    @Autowired
    private SystemConstants constants;
    @Value("${emos.image-folder}")
    private String imageFolder;

    @GetMapping("/validCanCheckin")
    @ApiOperation("查看用户当前是否可以进行签到")
    public R validCanCheckin(@RequestHeader("token") String token) {
        //从token中获取userId
        int userId = jwtUtil.getUserId(token);
        //校验是否可以进行签到
        String res = checkinService.validCanCheckin(userId, DateUtil.today());
        return R.ok(res);
    }

    @PostMapping("/checkin")
    @ApiOperation("签到")
    public R checkin(@Valid CheckinForm form, @RequestParam("photo") MultipartFile file, @RequestHeader("token") String token) {
        if (Objects.isNull(file)) {
            return R.error(constants.NO_FILE_UPLOAD);
        }
        /*从token中解析用户id*/
        int userId = jwtUtil.getUserId(token);
        /*获取文件名*/
        String fileName = file.getOriginalFilename().toLowerCase(Locale.ROOT);
        if (!fileName.endsWith(".jpg")) {
            return R.error(constants.IMAGE_FORMAT_ERROR);
        }
        /*完整的文件路径*/
        String path = imageFolder + "/" + fileName;
        try {
            file.transferTo(Paths.get(path));
            HashMap inParam = new HashMap();
            inParam.put("userId", userId);
            inParam.put("path", path);
            inParam.put("city", form.getCity());
            inParam.put("district", form.getDistrict());
            inParam.put("address", form.getAddress());
            inParam.put("country", form.getCountry());
            inParam.put("province", form.getProvince());
            checkinService.checkin(inParam);
            return R.ok(constants.CHECKIN_SUCCESS);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new EmosException(constants.IMAGE_SAVE_ERROR);
        } finally {
            /*不管签到有没有成功，删除原来的自拍照*/
            FileUtil.del(path);
        }
    }

    @PostMapping("/createFaceModel")
    @ApiOperation("创建人脸模型")
    public R createFaceModel(@RequestParam("photo") MultipartFile file,@RequestHeader("token") String token) {
        if (Objects.isNull(file)) {
            return R.error(constants.NO_FILE_UPLOAD);
        }
        /*从token中解析用户id*/
        int userId = jwtUtil.getUserId(token);
        /*获取文件名*/
        String fileName = Objects.requireNonNull(file.getOriginalFilename()).toLowerCase(Locale.ROOT);
        if (!fileName.endsWith(".jpg")) {
            return R.error(constants.IMAGE_FORMAT_ERROR);
        }
        /*完整的文件路径*/
        String path = imageFolder + "/" + fileName;
        try {
            file.transferTo(Paths.get(path));
            checkinService.createFaceModel(userId,path);
            return R.ok(constants.FACE_MODEL_CREATE_SUCCESS);
        } catch (IOException e){
            log.error(e.getMessage(), e);
            throw new EmosException(constants.IMAGE_SAVE_ERROR);
        } finally {
            /*删除原来的自拍照*/
            FileUtil.del(path);
        }
    }

    @GetMapping("/searchTodayCheckin")
    @ApiOperation("查询用户当日的签到数据")
    public R searchTodayCheckin(@RequestHeader("token") String token){
        /*从token中解析userId*/
        int userId = jwtUtil.getUserId(token);
        /*查询该用户当天的签到信息*/
        HashMap result = checkinService.searchTodayCheckin(userId);
        /*封装上班时间和下班时间*/
        result.put("attendanceTime",constants.attendanceTime);
        result.put("closingTime",constants.closingTime);
        /*查询当前用户的签到数*/
        long days = checkinService.searchCheckinDays(userId);
        result.put("checkinDays",days);
        /*查询用户的入职日期,将得到的日期转换成Date对象*/
        DateTime hireDate = DateUtil.parse(userService.searchUserHiredate(userId));
        result.put("hireDate",hireDate);
        /*获取本周的开始日期对象*/
        DateTime weekStartDate = DateUtil.beginOfWeek(DateUtil.date());
        /*比对本周开始日期和入职日期
        * 如果本周开始的日期早于入职日期
        * 则让该用户本周的开始日期为入职日期*/
        if (weekStartDate.isBefore(hireDate)){
            weekStartDate = hireDate;
        }
        /*获取本周结束日期对象*/
        DateTime weekEndDate = DateUtil.endOfWeek(DateUtil.date());
        /*封装查询入参*/
        HashMap inParam = new HashMap<>();
        inParam.put("startDate", weekStartDate.toString());
        inParam.put("endDate", weekEndDate.toString());
        inParam.put("userId", userId);
        /*查询本周签到信息*/
        ArrayList<HashMap> weekCheckin = checkinService.searchWeekCheckin(inParam);
        /*封装查询结果*/
        result.put("weekCheckin", weekCheckin);
        return R.ok().put("result", result);
    }

    @PostMapping("/searchMonthCheckin")
    @ApiOperation("查询员工月签到数据")
    public R searchMonthCheckin(@Valid @RequestBody SearchMonthCheckinForm form, @RequestHeader("token") String token) {
        /*解析用户id*/
        int userId = jwtUtil.getUserId(token);
        /*查询员工入职日期*/
        String hiredateStr = userService.searchUserHiredate(userId);
        DateTime hiredate = DateUtil.parse(hiredateStr);
        String month = form.getMonth() < 10 ? "0" + form.getMonth() : form.getMonth().toString();
        DateTime startDate = DateUtil.parse(form.getYear() + "-" + form.getMonth() + "-01");
        /*员工入职月份和当前月份作比较*/
        if (startDate.isBefore(DateUtil.beginOfMonth(hiredate))) {
            /*要查询的月份早于员工入职的月份,抛出异常信息*/
            throw new EmosException(constants.MONTH_CHECKIN_SEARCH_ERROR);
        }
        if (startDate.isBefore(hiredate)) {
            /*进入这个分支说明要查询的月份等于员工入职的月份
             * 将员工的入职日期作为开始日期查询*/
            startDate = hiredate;
        }
        /*获取这个月截止日期*/
        DateTime endDate = DateUtil.endOfMonth(startDate);
        /*封装查询参数*/
        HashMap inParam = new HashMap();
        inParam.put("userId", userId);
        inParam.put("startDate", startDate.toString());
        inParam.put("endDate", endDate.toString());
        ArrayList<HashMap> result = checkinService.searchMonthCheckin(inParam);
        /*数据统计 sum_1:正常签到天数 sum_2:迟到天数 sum_3:缺勤天数*/
        int sum_1 = 0, sum_2 = 0, sum_3 = 0;
        for (HashMap<String, String> one : result) {
            /*当天是工作日还是休息日*/
            String dateType = one.get("type");
            /*考勤状态*/
            String status = one.get("status");
            if (constants.CODE_WORKDAY.equals(dateType)) {
                if (constants.CODE_NORMAL.equals(status)) {
                    /*这天是工作日并且正常签到*/
                    sum_1++;
                } else if (constants.CODE_LATE.equals(status)) {
                    /*这天是工作日但是迟到*/
                    sum_2++;
                } else if (constants.CODE_ABSENCE.equals(status)) {
                    /*这天是工作日但是缺勤*/
                    sum_3++;
                }
            }
        }
        return R.ok().put("result", result).put("sum_1", sum_1).put("sum_2", sum_2).put("sum_3", sum_3);
    }
}